package com.net.xpay.common.service.impl;

import com.net.xpay.common.domain.User;
import com.net.xpay.common.domain.UserShard;
import com.net.xpay.common.domain.stat.UserSafePayTransMonthStat;
import com.net.xpay.common.domain.stat.UserSafePayTransStat;
import com.net.xpay.common.helper.NoticeHelper;
import com.net.xpay.common.manager.UserManager;
import com.net.xpay.common.manager.UserShardManager;
import com.net.xpay.common.manager.stat.UserSafePayTransMonthStatManager;
import com.net.xpay.common.manager.stat.UserSafePayTransStatManager;
import com.net.xpay.common.model.UserSafePayTransStatMonthModel;
import com.net.xpay.core.manager.safePay.BookAccountChargeOrderManager;
import com.net.xpay.core.manager.safePay.SafePayBatchManager;
import com.net.xpay.core.model.UserSafePayTransStatCommonModel;
import com.net.xpay.core.model.UserSafePayTransStatModel;
import com.net.common.util.LocalDateUtil;
import com.net.common.util.SerializationUtil;
import com.net.xpay.common.service.UserSafePayTransStatService;
import com.net.shard.ShardUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

@Service
@Slf4j
public class UserSafePayTransStatServiceImpl implements UserSafePayTransStatService {

    @Autowired
    private UserSafePayTransStatManager userSafePayTransStatManager;

    @Autowired
    private UserSafePayTransMonthStatManager userSafePayTransMonthStatManager;

    @Autowired
    private UserManager userManager;

    @Autowired
    private UserShardManager userShardManager;

    @Autowired
    private SafePayBatchManager safePayBatchManager;

    @Autowired
    private NoticeHelper noticeHelper;

    @Autowired
    private BookAccountChargeOrderManager bookAccountChargeOrderManager;

    @Override
    public void doUserSafePayTransStat(LocalDate day) {
        // 调用UserManager获取所有的user
        List<User> userList = userManager.listAll();
        // 进行预判空处理
        if (CollectionUtils.isEmpty(userList)) {
            log.warn("doUserSafePayTransStat There are no users at this time");
            return;
        }
        userList.forEach(user -> {
            UserSafePayTransStat userTransStat = new UserSafePayTransStat();
            // 通过userID获取到userShard
            UserShard userShard = userShardManager.getById(user.getId());
            try {
                // 先去判断该用户当天转账金额记录是否存在
                userTransStat.setDay(day);
                userTransStat.setYear(day.getYear());
                userTransStat.setMonth(day.getMonthValue());
                userTransStat.setUserId(user.getId());
                userTransStat.setPartnerId(user.getPartnerId());
                userTransStat.setFatherPartnerId(user.getFatherPartnerId());
                boolean exitRecord = hasStated(userTransStat);
                if (exitRecord) {
                    log.warn("doUserSafePayTransStat the record of userId={}|day={} is already exist", user.getId(), day);
                    return;
                }
                // 切库处理
                ShardUtil.setShardContext(userShard.getShardId());
                // 获取当天的起始时间和终止时间 终止时间保留在23:59:59.999999999
                LocalDateTime minEndTime = LocalDateUtil.getDayStart(day);
                LocalDateTime maxEndTime = LocalDateUtil.getDayEnd(day);
                UserSafePayTransStatModel userTransStatModel = safePayBatchManager.countAmountAndTimesOfSuccess(user.getId(), minEndTime, maxEndTime);
                UserSafePayTransStatCommonModel userSafePayTransStatCommonBankModel = safePayBatchManager.countAmountAndTimesOfSuccessBank(user.getId(), minEndTime, maxEndTime);
                UserSafePayTransStatCommonModel userSafePayTransStatCommonAlipayModel = safePayBatchManager.countAmountAndTimesOfSuccessAlipay(user.getId(), minEndTime, maxEndTime);
                //不免费的统计
                UserSafePayTransStatCommonModel userSafePayTransStatCommonNotFreeBankModel = safePayBatchManager.countAmountAndTimesOfSuccessNotFreeBank(user.getId(), minEndTime, maxEndTime);
                UserSafePayTransStatCommonModel userSafePayTransStatCommonNotFreeAlipayModel = safePayBatchManager.countAmountAndTimesOfSuccessNotFreeAlipay(user.getId(), minEndTime, maxEndTime);
                BeanUtils.copyProperties(userTransStatModel, userTransStat);
                //到卡
                userTransStat.setSuccessBankAmount(userSafePayTransStatCommonBankModel.getSuccessAmount());
                userTransStat.setSuccessBankCount(userSafePayTransStatCommonBankModel.getSuccessCount());
                //到支付宝
                userTransStat.setSuccessAlipayAmount(userSafePayTransStatCommonAlipayModel.getSuccessAmount());
                userTransStat.setSuccessAlipayCount(userSafePayTransStatCommonAlipayModel.getSuccessCount());
                //不免费到卡
                userTransStat.setNotFreeSuccessBankAmount(userSafePayTransStatCommonNotFreeBankModel.getSuccessAmount());
                userTransStat.setNotFreeSuccessBankCount(userSafePayTransStatCommonNotFreeBankModel.getSuccessCount());
                //不免费到支付宝
                userTransStat.setNotFreeSuccessAlipayAmount(userSafePayTransStatCommonNotFreeAlipayModel.getSuccessAmount());
                userTransStat.setNotFreeSuccessAlipayCount(userSafePayTransStatCommonNotFreeAlipayModel.getSuccessCount());
                //不免费的总金额 / 笔数
                userTransStat.setNotFreeSuccessAmount(new BigDecimal(userSafePayTransStatCommonNotFreeBankModel.getSuccessAmount()).add(new BigDecimal(userSafePayTransStatCommonNotFreeAlipayModel.getSuccessAmount())).toString());
                userTransStat.setNotFreeSuccessCount(userSafePayTransStatCommonNotFreeBankModel.getSuccessCount() + userSafePayTransStatCommonNotFreeAlipayModel.getSuccessCount());
                // 当天成功充值的账本本金
                BigDecimal bookAccountChargeSuccessAmount = bookAccountChargeOrderManager.sumSuccessTransAmount(user.getId(), minEndTime, maxEndTime);
                userTransStat.setBookAccountChargeAmount(bookAccountChargeSuccessAmount);

                // 数据入库
                userSafePayTransStatManager.save(userTransStat);
            } finally {
                ShardUtil.cleanShardContext();
            }
        });
    }

    @Override
    public void doUserSafePayTransMonthStat(Integer year, Integer month) {
        // 调用UserManager获取所有的user
        List<User> userList = userManager.listAll();

        // 进行预判空处理
        if (CollectionUtils.isEmpty(userList)) {
            log.warn("doUserSafePayTransMonthStat There are no users at this time");
            return;
        }
        userList.forEach(user -> {
            boolean exitRecord = hasMonthStated(year, month, user.getId());
            if (exitRecord) {
                log.warn("doUserSafePayTransMonthStat the record of userId={}|year={}|month={} is already exist", user.getId(), year, month);
                return;
            }
            List<UserSafePayTransStatMonthModel> userSafePayTransStatMonthModels = userSafePayTransStatManager.sumMonthUserSafePayTransStat(year, month, user.getId());
            //合伙人在一个月内变更过
            if (userSafePayTransStatMonthModels.size() > 1) {
                log.warn("doUserSafePayTransMonthStat user has change partner|userId={}|userSafePayTransStatMonthModels={}", user.getId(), SerializationUtil.obj2String(userSafePayTransStatMonthModels));
            }
            for (UserSafePayTransStatMonthModel statMonthModel : userSafePayTransStatMonthModels) {
                UserSafePayTransMonthStat userTransStat = new UserSafePayTransMonthStat();
                userTransStat.setYear(year);
                userTransStat.setMonth(month);
                userTransStat.setUserId(statMonthModel.getUserId());
                userTransStat.setPartnerId(statMonthModel.getPartnerId());
                userTransStat.setFatherPartnerId(statMonthModel.getFatherPartnerId());
                BeanUtils.copyProperties(statMonthModel, userTransStat);
                userSafePayTransMonthStatManager.save(userTransStat);
            }
        });
    }

    private boolean hasMonthStated(int year, int month, Long userId) {
        // 尝试通过时间加id获取数据
        UserSafePayTransMonthStat record = userSafePayTransMonthStatManager.findByMonthOfYear(year, month, userId);
        // 若果查到了数据，表示不需要在插入记录了
        return record != null;
    }


    private boolean hasStated(UserSafePayTransStat userTransStat) {
        LocalDate day = userTransStat.getDay();
        Long userId = userTransStat.getUserId();
        // 尝试通过时间加id获取数据
        UserSafePayTransStat userTransStatRecord = userSafePayTransStatManager.findByDayAndUserId(day, userId);
        // 若果查到了数据，表示不需要在插入记录了
        return userTransStatRecord != null;
    }
}
